import { Window_Base } from "@/windows/Window_Base.js";
import { TextInterpreter } from "@/utils/TextInterpreter.js";
import { ColorExtraction } from "@/utils/ColorExtraction.js";
import { TouchInput } from "@/core/TouchInput.js";
import { Sprite_PauseSign } from "@/sprites/Sprite_PauseSign.js";
import { config } from "@/managers/ConfigManager.js";

export class Window_Message extends Window_Base {
    static slowCont = 15;
    static fastCount = 5;
    constructor(width, height) {
        super(width, height);

        this.visible=false;
        this.active=false;
        this._pause = false;
        this.text = '';
        this.crtIndex = 0;

        this.varibaleText = '';
        this.crtVarIndex = 0;

        this.outputX = 0;
        this.outputY = 0;
        this.maxHeight = this.lineHeight();
        this.waitCount = 10;

        this.willWaitCount = Window_Message.slowCont;
        this.restState = null;

        this.pauseSign = new Sprite_PauseSign();
        this.addChild(this.pauseSign);
    }

    activate(){
        this.active=true;
        this.open();
    }

    deactivate(){
        this.active=false;
        this.close();
    }

    start(text) {
        this.text = text;
        this.contents.clear();
        this.outputX = this.getInitOutPutX();
        this.outputY = 0;
        this.lineHeight = this.lineHeight();
        this.pauseSign.visible = false;
        this.activate();
        if (this._pause) {
            this.resume();
        }
    }
    clear() {
        this.text = '';
        this.contents.clear();
        this.outputX = this.getInitOutPutX();
        this.outputY = 0;
        this.lineHeight = this.lineHeight();
        this.pauseSign.visible = false;
        this._pause = false;
    }

    pause() {
        this._pause = true;
        //调出暂停悬浮箭头
        this.pauseSign.visible = true;
        this.pauseSign.move(this.outputX + this._padding - 12, this.outputY + this._padding + 3);
    }

    resume() {
        this._pause = false;
        if (this.outputX == this.getInitOutPutX() && this.outputY == 0) {
            this.contents.clear();
        }
        this.pauseSign.visible = false;
    }

    newPagePause() {
        this.pause();
        if (this.maxHeight > this.contentsHeight()) {
            this.clear();
            this.close();
            return;
        }
        this.outputX = this.getInitOutPutX();
        this.outputY = 0;
    }

    getInitOutPutX() {
        return 0;
    }

    isIntByVariable() {
        return this.crtVarIndex < this.varibaleText.length && this.varibaleText.length > 0;
    }

    isEnd() {
        return !this.text && !this.varibaleText;
    }

    inValidOutPutCoord(width) {
        if (this.outputX + width > this.contentsWidth()) {
            this.outputX = this.getInitOutPutX();
            this.outputY += this.maxHeight;
            if (this.outputY > this.contentsHeight() - this.maxHeight) {
                this.newPagePause();
                return false;
            }
        }
        return true;
    }

    updateSelf() {
        if (this.active) {
            if (!this._pause) {
                if (this.waitCount <= 0) {
                    this.updateMessage();
                    this.waitCount = this.willWaitCount;
                } else {
                    --this.waitCount;
                }
            }
            this.updateInteractive();
        }
    }

    updateInteractive() {
        if (TouchInput.isTriggered()) {
            if (!this._pause) {
                this.willWaitCount = 0;
            } else {
                if (!this.text && !this.varibaleText) {
                    this.close();
                } else {
                    this.resume();
                }
                this.willWaitCount = Window_Message.slowCont;
            }
        }
    }

    updateMessage() {
        if (this.text || this.varibaleText) {
            if (this.isIntByVariable()) {
                let symbol = this.varibaleText[this.crtVarIndex];
                let width = this.textWidth(symbol);
                if (this.inValidOutPutCoord(width)) {
                    this.drawText(symbol, this.outputX, this.outputY, width, this.maxHeight);
                    this.outputX += width;
                    ++this.crtVarIndex;
                    if (this.crtVarIndex >= this.varibaleText.length) {
                        this.varibaleText = '';
                        this.crtVarIndex = 0;
                    }
                }
            } else {
                let symbol = this.text[this.crtIndex];
                if (!this.drawSymbol(symbol)) {
                    if (symbol == '\n') {
                        this.inValidOutPutCoord(this.contentsWidth());
                    } else {
                        this.drawNormalChar(symbol);
                    }
                }
                ++this.crtIndex;
                if (this.crtIndex >= this.text.length) {
                    this.text = '';
                    this.crtIndex = 0;
                }
            }

            if (this.isEnd()) {
                this.pause();
            }
        } else {
            this.close();
        }
    }

    drawSymbol(symbol) {
        if (symbol == '\\') {
            let state = null;
            if (this.restState) {
                state = this.restState;
                this.restState = null;
            } else {
                state = TextInterpreter.parse(this.text, this.crtIndex);
            }

            if (!state.failed) {
                switch (state.type) {
                    case 'V':
                        this.varibaleText = String($gameVariables.value(TextInterpreter.DismantleVariables(state)));
                        this.crtVarIndex = 0;
                        break;
                    case 'C':
                        this.changeTextColor(
                            ColorExtraction.textColor(
                                TextInterpreter.DismantleVariables(state)
                            )
                        );
                        break;
                    case 'I':
                        if (this.inValidOutPutCoord(config.iconSize)) {
                            this.drawIcon(
                                TextInterpreter.DismantleVariables(state),
                                this.outputX,
                                this.outputY
                            );
                            this.outputX += config.iconSize;
                            if (this.maxHeight < config.iconSize) {
                                this.maxHeight = config.iconSize;
                            }
                        } else {
                            this.restState = state;
                            --this.crtIndex;
                            return true;
                        }
                        break;
                    case '{':
                        this.makeFontBigger();
                        this.maxHeight = this.contents._fontSize + 8;
                        break;
                    case '}':
                        this.makeFontSmaller();
                        if (this.outputX == this.getInitOutPutX()) {
                            this.maxHeight = this.contents._fontSize + 8;
                        }
                        break;
                }
                this.crtIndex = state.nexti;
                return true;
            }
        }
        return false;
    }

    drawNormalChar(char) {
        let width = this.textWidth(char);
        if (this.inValidOutPutCoord(width)) {
            this.drawText(char, this.outputX, this.outputY, width, this.maxHeight);
            this.outputX += width;
        }
    }
}